package xyz.scootaloo.kami.cloud

import io.vertx.core.CompositeFuture
import io.vertx.core.Future
import io.vertx.core.Vertx
import io.vertx.core.impl.cpu.CpuCoreSensor
import io.vertx.kotlin.core.deploymentOptionsOf
import io.vertx.kotlin.core.vertxOptionsOf
import xyz.scootaloo.kami.cloud.lang.Global
import xyz.scootaloo.kami.cloud.lang.getLogger
import xyz.scootaloo.kami.cloud.verticle.HttpServerVerticle
import xyz.scootaloo.kami.cloud.verticle.StateCenterVerticle

/**
 * 遵循vertx最佳实践的重构版本
 *
 * @author flutterdash@qq.com
 * @since 2022/4/10 13:58
 */
class KamiCloudFinal(
    private val sysConf: ServerConfig = ServerConfig(),
    private val fileConf: FileConfig = FileConfig(),
    private val logConfig: LogConfig = LogConfig()
) {
    init {
        System.setProperty("log4j.skipJansi", "false") // 启用彩色日志
    }

    private val log = getLogger("kami-cloud-final")

    fun start(): CompositeFuture {
        publishGlobalConf()
        Global.VERTX_REF = prepareDefVertxRef()
        val f1 = Global.VERTX_REF.deployVerticle(HttpServerVerticle)
        val f2 = Global.VERTX_REF.deployVerticle(StateCenterVerticle)
        return CompositeFuture.all(f1, f2).onFailure { err ->
            log.error("系统启动失败", err)
            shutdown()
        }
    }

    fun shutdown(): Future<Void> {
        val f1 = Global.VERTX_REF.undeploy(HttpServerVerticle.deploymentId())
        val f2 = Global.VERTX_REF.undeploy(StateCenterVerticle.deploymentId())
        return CompositeFuture.all(f1, f2).transform {
            Global.VERTX_REF.close().onComplete {
                log.info("系统关闭")
            }
        }
    }

    private fun publishGlobalConf() {
        Global.APP_SER_CONF = sysConf
        Global.APP_FILE_CONF = fileConf
        Global.APP_LOG_CONF = logConfig
    }

    private fun prepareDefVertxRef(): Vertx {
        return Vertx.vertx(vertxDefOptions())
    }

    private fun vertxDefOptions() = vertxOptionsOf(
        eventLoopPoolSize = 4,
        workerPoolSize = cpuCoreSensorCount() * 1,
        internalBlockingPoolSize = cpuCoreSensorCount() * 1
    )

    private fun cpuCoreSensorCount(): Int {
        return CpuCoreSensor.availableProcessors()
    }

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            KamiCloudFinal().start()
        }
    }

}